const log = console.log
// 1 字符串构造函数
let fn1 = () => {
  // 构造字符串常量
  let str = String(1)
  // 构造字符串对象
  let str1 = new String(1)
  // 使用直接字面量
  let str2 = '"'
  let st = 'hello'
  // 使用模板字符串
  let str3 = `"${st}"`
  console.log(str, str1, str2, str3) // 1 String {'1'} " "hello"
}

// 2 字符串迭代器和length属性，遍历字符串 for-of for
let fn2 = () => {
  let str = '123456'
  // 第1种遍历方法 for-of
  for (let item of str) {
    console.log(item)
  }

  // for (let item of str[Symbol.iterator]()) {
  //   console.log(item)
  // }
  // 字符串解构
  // let arr = [...str]
  // console.log(arr)
  // 获得字符串的迭代器
  // let it = str[Symbol.iterator]()
  // let rt = it.next().value
  // console.log(rt)

  // 第2种遍历方法,使用下标方法 for+index
  for (let i = 0; i < str.length; i++) {
    console.log(str[i]) // 输出字符串中的每个字符
  }

  // 第3种遍历方法 for-in
  for (let index in str) {
    console.log(str[index])
  }

  // 第4种遍历方法 字符转数组
  Array.from(str).forEach((item) => console.log(item))

  // 第5种遍历方法 字符串解构成数组
  let arr = [...str]
  arr.forEach((item) => console.log(item))
}

// 3 at() charAt() 获得指定下标的字符
let str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
let fn3 = () => {
  log(str.at(0), str.charAt(str.length - 1)) // a Z
}

// 4 charCodeAt(index) 把index位置的字符转换成功数字
let fn4 = () => {
  let str = '大王'
  log(str.charCodeAt(0), str.charCodeAt(1)) // 22823 29579
  log(String.fromCharCode(29579)) // 王
}

// 5 concat() 拼接字符串
let fn5 = () => {
  let str = '大王'
  str = str.concat('叫我来巡山', 123, 456)
  log(str) // 大王叫我来巡山123456
}

// 6 endsWith(str) 判断是否是str结尾
let fn6 = () => {
  let fileName = 'hello.gif'
  // 判断fileName是否是图片名称
  let list = ['png', 'jpg', 'jpeg', 'bmp', 'svg', 'webp', 'gif']
  let result = false
  for (let item of list) {
    if (fileName.endsWith(item)) {
      result = true
      break
    }
  }
  log(`${fileName}是图片吗:${result}`)
}

// 7 String.fromCharCode(number) 0<=number<=65535 把指定数字转换为字符
let fn7 = () => {
  let list = []
  for (let i = 97; i <= 122; i++) {
    list.push(String.fromCharCode(i))
  }
  log(list) //['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
}

// 8 includes(str) 判断字符串是否包含子字符串str
let fn8 = () => {
  log(str.includes('abcde')) // true
  log(str.includes('abce')) // false
}

// 9 indexOf(str) str首次出现的位置，如果没有返回-1
let fn9 = () => {
  // 只要字符串中包含@就是邮箱
  let email = '95243611@qq.com'
  let index = email.indexOf('@')
  if (index !== -1) {
    log(`${email}是邮箱地址`)
  } else {
    log(`${email}不是邮箱地址`)
  }
}

// 10 lastIndexOf(str) str最后出现的位置，如果没有返回-1
let fn10 = () => {
  // 只要字符串中包含@并且只有一个就是邮箱
  let email = '95243611@qq.com'
  let index = email.indexOf('@')
  let lastIndex = email.lastIndexOf('@')
  if (index !== -1 && index === lastIndex) {
    log(`${email}是邮箱地址`)
  } else {
    log(`${email}不是邮箱地址`)
  }
}

// 11 match(reg) 使用指定字符或正则表达式匹配字符串中的字符
let fn11 = () => {
  let list = []
  let fileNames = ['王海20220928.zip', '丁旺20220928.zip']
  for (let fileName of fileNames) {
    // 把汉字，数字，字母提取出来
    let reg = /\d/g // 全局匹配所有的数字
    let number = fileName.match(reg) // ['2', '0', '2', '2', '0', '9', '2', '8']
    reg = /[\u4e00-\u9fa5]/g // 匹配汉字
    let code = fileName.match(reg) // ['王', '海']
    reg = /[a-zA-Z]/g // 匹配字母
    let letter = fileName.match(reg) // ['z', 'i', 'p']
    // console.log(code, number, letter)
    list.push(code.join(''))
  }
  console.log(list)
}

// 12 padEnd() padStart() 填充字符
let fn12 = () => {
  let str = '1'.padStart(3, '0')
  log(str) // 001字符串
  let str1 = '1111'.padEnd(3, '#')
  log(str1) // 1111 字符串a
  let date = new Date()
  let y = date.getFullYear()
  let m = (date.getMonth() + 1 + '').padStart(2, '0')
  let d = (date.getDate() + '').padStart(2, '0')
  let h = (date.getHours() + '').padStart(2, '0')
  let M = (date.getMinutes() + '').padStart(2, '0')
  let s = (date.getSeconds() + '').padStart(2, '0')
  log([y, m, d].join('-').concat(' ', [h, M, s].join(':')))
}
// fn12()

// 13 repeat(n) 字符串重复次数
let fn13 = () => {
  log('abc'.repeat(5)) // abcabcabcabcabc
}
// fn13()

// 14 repeat() repeatAll() 使用指定字符串或正则替换
let fn14 = () => {
  let p = 'Lazy dog?. If the Dog reacted, was it really lazy dog?'
  // 使用指定字符monkey替换字符串中的dog,只能替换第一个
  // let p1 = p.replace('dog', 'monkey')
  let p1 = p.replace('dog', (item) => (item = 'monkey'))
  log(p1) // Lazy monkey?. If the dog reacted, was it really lazy?
  // 使用正则表达式对字符串中的dog进行替换,可以全部替换或替换一个
  // let p2 = p.replace(/dog/gi, 'ferret')
  let p2 = p.replace(/dog/gi, (item) => (item = 'ferret'))
  log(p2) // Lazy ferret?. If the ferret reacted, was it really lazy?

  // repeatAll() 全部替换
  let p3 = p.replaceAll('dog', 'cat')
  log(p3) // Lazy cat?. If the Dog reacted, was it really lazy cat?
  let p4 = p.replaceAll(/dog/gi, 'parrot')
  log(p4) // Lazy parrot?. If the parrot reacted, was it really lazy parrot?
}

// 15 search() 搜索首次出现的位置
let fn15 = () => {
  // let str = 'Lazy cat!?Lazy cat?Lazy cat?'
  let str = '张三20220910.zip'
  let reg = /[^\w\s\u4e00-\u9fa5]/g // 匹配不是空格数字字母下划线的字符
  let index = str.search(reg) // ?字符在str中首次出现的下标
  log(str[index]) // ?
}

// 16 slice(s,e) 从s开始到e结束，截取此下标范围字符串[s,e)
let fn16 = () => {
  let p = 'Lazy dog? If the Dog reacted, was it really lazy dog?'
  log(p.slice(8)) // ? If the Dog reacted, was it really lazy dog?
  log(p.slice(8, 14)) // ? If t
}

// 17 split(code) 使用指定的字符code分割字符串为数组
let fn17 = () => {
  let p = 'Lazy d,og'
  log(p.split(/\s/)) // 使用空格正则分割字符串为数组 [ 'Lazy', 'd,og' ]
  log(p.split(' ')) // 使用空格字符分割字符串为数组 [ 'Lazy', 'd,og' ]
  log(p.split(',')) // [ 'Lazy d', 'og' ]
  log(p.split('')) // 使用空字符串拆分每个字符为数组元素['L', 'a', 'z','y', ' ', 'd',',', 'o', 'g']
}

// 18 startsWith() 以指定字符开头
let fn18 = () => {
  let str = '$1200.00'
  console.log(str.startsWith('$12')) // true
}

// 19 substring(s,e) 截取字符串
let fn19 = () => {
  // 判断日期格式是否正确
  let str = '2003-04-30 12:09:01'
  let list = str.split(' ') // ['1900-01-01','12:09:01']
  let left = list[0].split('-') // ['1900','01','01']
  let right = list[1].split(':') // ['12','09','01']
  let y = +left[0]
  // 当前年
  let now = new Date().getFullYear()
  if (isNaN(y) || y < 0 || y > now) {
    log('年分必须存在，且在0-' + now + '范围')
    return false
  }
  let m = +left[1]
  if (isNaN(m) || m < 1 || m > 12) {
    log('月份分必须存在，且在1-12范围')
    return false
  }
  let days = 28
  if ((y % 4 === 0 && y % 100 !== 0) || y % 400 === 0) {
    days = 29
  }
  // 月份最大天数的下标
  let arr = [31, days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  // 1-28 29 30 31
  let d = +left[2]
  if (isNaN(d) || d < 1 || d > arr[m - 1]) {
    log(`${m}月中的天必须在1-${arr[m - 1]}范围`)
    return false
  }
  // 判断时分秒...
}

let fn20 = () => {
  let str = '2003-04-30 12:39:00'
  let reg = /^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}$/
  if (!reg.test(str)) {
    console.log('非法的时间格式')
    return false
  }
  let h = +str.substring(11, 13)
  // 验证时间范围0-23
  if (h < 0 || h > 23) {
    log('时间范围0-23')
    return false
  }
  let m = +str.substring(14, 16)
  if (m < 0 || m > 59) {
    log('分钟范围0-59')
    return false
  }
  let s = +str.substring(17)
  if (s < 0 || s > 59) {
    log('秒钟范围0-59')
    return false
  }
  log(h, m, s) // 12 39 7
  return true
}

// 21 toUpperCase() 转大写
let fn21 = () => {
  let str = 'Hello world!'
  log(str.toUpperCase()) // HELLO WORLD!
}
fn21()

// 22 toLowerCase() 转小写
let fn22 = () => {
  let str = 'Hello World!'
  log(str.toLowerCase()) // hello world!
}
// fn22()

// 23 trim() 去除收尾空格
let fn23 = (n) => {
  let str = '   Hello World!   '
  console.log('$' + str + '$') // $   Hello World!   $
  str = str.trim()
  console.log('$' + str + '$') // $Hello World!$
}

// 24 trimStart() 去开头空格
let fn24 = (n) => {
  let str = '   Hello World!   '
  console.log('$' + str.trimStart() + '$') // $Hello World!   $
}

// 25 trimEnd() 去末尾空格
let fn25 = (n) => {
  let str = '   Hello World!   '
  console.log('$' + str.trimEnd() + '$') // $   Hello World!$
}

// 去除所有空格
let fn26 = () => {
  let str = '   Hello World!   '
  // 方法1
  let list = str.split('')
  list = list.filter((item) => item !== ' ')
  console.log('$' + list.join('') + '$') // $HelloWorld!$
  // 方法2
  str = str.replace(/\s/g, '')
  console.log('$' + str + '$')
}
fn26()
// 26 toString() 转字符串
